package com.jiuqi.abc.model.service;

import com.jiuqi.abc.model.bean.Driver;
import com.jiuqi.abc.model.bean.DriverGroup;
import com.jiuqi.abc.model.bean.DriverItem;
import com.jiuqi.abc.model.bean.DriverItemFormula;
import com.jiuqi.abc.model.dao.ABCDriverGroupDao;
import com.jiuqi.bi.util.Guid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 动因分组service
 *
 * @author 龚泽楷
 * @date 2023年04月23日 14:02
 */
@Service
public class ABCDriverGroupService {

    @Autowired
    private ABCBeanService abcBeanService;

    @Autowired
    private ABCDriverGroupDao abcDriverGroupDao;

    @Autowired
    private ABCDriverGroupService driverGroupService;

    @Autowired
    private ABCDriverService abcDriverService;

    @Autowired
    private ABCDriverItemService abcDriverItemService;

    @Autowired
    private ABCDriverItemFormulaService abcDriverItemFormulaService;

    /**
     * 添加动因分组
     * <p>
     * 动因分组自动命名策略：默认以 “动因分组”+ N 的形式进行增加，遇缺则补
     * 例如 已有 动因分组1 动因分组2 动因分组3     新增加  动因分组4
     * 例如 已有 动因分组1 动因分组3 动因分组4     新增加  动因分组2
     *
     * @param driverGroup 动因分组实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDriverGroup(DriverGroup driverGroup) {
        //自动生成 动因分组名称
        List<DriverGroup> driverGroupList = getDriverGroupListByModelId(driverGroup.getBelongModelId());
        int preNumPart = 1;
        String preSetName = String.format("动因分组%d", preNumPart);

        //检测当前名称是否存在
        List<String> existedTitleList = driverGroupList.stream().map(DriverGroup::getTitle).collect(Collectors.toList());
        boolean flag = true;
        do {
            if (!existedTitleList.contains(preSetName)) {
                flag = false;
            } else {
                preNumPart++;
                preSetName = String.format("动因分组%d", preNumPart);
            }
        } while (flag);

        driverGroup.setTitle(preSetName);

        List<DriverGroup> driverGroups = new ArrayList<>();
        driverGroups.add(driverGroup);
        abcDriverGroupDao.batchSaveDriverGroups(driverGroups);

        //更新abc模型的修改时间
        if (!driverGroups.isEmpty()) {
            String modelId = driverGroups.get(0).getBelongModelId();
            abcBeanService.updateModifyTime(modelId);
        }
    }

    /**
     * 批量添加 动因分组详细信息集合
     * @param driverGroups 动因分组详细信息集合
     * @param modelId 模型ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDetailDriverGroups(List<DriverGroup> driverGroups,String modelId) {
        //添加动因分组
        for (DriverGroup driverGroup : driverGroups){
            driverGroup.setBelongModelId(modelId);
        }
        abcDriverGroupDao.batchSaveDriverGroups(driverGroups);

        //添加动因
        for (DriverGroup driverGroup : driverGroups) {
            List<Driver> driverList = driverGroup.getDriverList();

            for (Driver driver : driverList) {
                driver.setBelongDriverGroupId(driverGroup.getKey());
                driver.setBelongModelId(driverGroup.getBelongModelId());
            }
            abcDriverService.batchAddDriversAndDriverItems(driverList);
        }

        //更新abc模型的修改时间
        abcBeanService.updateModifyTime(modelId);
    }

    /**
     * 将 旧模型guid 对应模型中 的 动因分组信息 复制到 新模型guid 对应模型中
     * @param oldAbcModelGuid 旧模型guid
     * @param newAbcModelGuid 新模型guid
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveAsDriverGroups(String oldAbcModelGuid,String newAbcModelGuid) {
        //复制源
        List<DriverGroup> detailDriverGroupListByModelId = getDetailDriverGroupListByModelId(oldAbcModelGuid);

        //处理 动因分组集合
        List<DriverGroup> processDriverGroupList = new ArrayList<>();
        for (DriverGroup driverGroup : detailDriverGroupListByModelId) {
            DriverGroup tempDriverGroup = new DriverGroup();
            BeanUtils.copyProperties(driverGroup, tempDriverGroup);

            tempDriverGroup.setDriverList(null);
            tempDriverGroup.setBelongModelId(newAbcModelGuid);
            tempDriverGroup.setKey(Guid.newGuid());

            processDriverGroupList.add(tempDriverGroup);

            //处理 动因集合
            List<Driver> processDriverList = new ArrayList<>();
            List<Driver> driverList = driverGroup.getDriverList();
            if (driverList != null) {
                for (Driver driver : driverList) {
                    driver.setBelongModelId(newAbcModelGuid);
                    driver.setBelongDriverGroupId(tempDriverGroup.getKey());
                    driver.setId(Guid.newGuid());

                    //处理 动因项集合
                    for (DriverItem driverItem : driver.getDriverItemList()) {
                        driverItem.setBelongModelId(newAbcModelGuid);
                        driverItem.setBelongDriverGroupId(tempDriverGroup.getKey());
                        driverItem.setBelongDriverId(driver.getId());
                        driverItem.setId(Guid.newGuid());

                        //处理 动因项公式
                        DriverItemFormula driverItemFormula = driverItem.getDriverItemFormula();
                        driverItemFormula.setBelongModelId(newAbcModelGuid);
                        driverItemFormula.setBelongDriverItemId(driverItem.getId());
                    }
                    processDriverList.add(driver);
                }
            }
            abcDriverService.batchAddDriversAndDriverItems(processDriverList);
        }
        abcDriverGroupDao.batchSaveDriverGroups(processDriverGroupList);
    }

    /**
     * 根据 动因分组ID 获取 动因分组
     * @param driverGroupId 动因分组ID
     * @return 动因分组
     */
    public DriverGroup getDriverGroupByDriverGroupId(String driverGroupId) {
        return abcDriverGroupDao.getDriverGroupByDriverGroupId(driverGroupId);
    }


    /**
     * 根据 模型ID 获取 动因分组集合
     *
     * @param modelId 模型表主键
     * @return 动因分组集合 【动因分组 中 没有装配 动因】
     */
    public List<DriverGroup> getDriverGroupListByModelId(String modelId) {
        return abcDriverGroupDao.getDriverGroupListByModelId(modelId);
    }

    /**
     * 根据 模型ID 获取 动因分组详细信息集合
     * @param modelId 模型表主键
     * @return 动因分组集合 【动因分组 中 装配了 动因，各动因 中 装配 动因项, 各动因项 中 装配 动因项公式】
     */
    public List<DriverGroup> getDetailDriverGroupListByModelId(String modelId) {
        //获取 动因分组集合
        List<DriverGroup> driverGroups = abcDriverGroupDao.getDriverGroupListByModelId(modelId);

        //获取 动因集合
        List<String> driverGroupIdList = new ArrayList<>();
        for (DriverGroup driverGroup : driverGroups) {
            driverGroupIdList.add(driverGroup.getKey());
        }
        List<Driver> drivers = abcDriverService.getDriverListByDriverGroupIds(driverGroupIdList);

        //获取 动因项集合
        List<String> driverIdList = new ArrayList<>();
        for (Driver driver : drivers) {
            driverIdList.add(driver.getId());
        }
        List<DriverItem> driverItems = abcDriverItemService.getDriverItemListByDriverIds(driverIdList);

        //获取 动因项取数公式集合
        List<String> driverItemIdList = new ArrayList<>();
        for (DriverItem driverItem : driverItems) {
            driverItemIdList.add(driverItem.getId());
        }
        List<DriverItemFormula> driverItemFormulas = abcDriverItemFormulaService.batchGetDriverItemFormulaByDriverItemIdList(driverItemIdList);

        //动因项公式  装配至  动因项
        driverItemFormulas.forEach(
                driverItemFormulaItem ->
                        driverItems.stream()
                                .filter(driverItem -> driverItemFormulaItem.getBelongDriverItemId().equals(driverItem.getId()))
                                .forEach(selectedDriverItem -> selectedDriverItem.setDriverItemFormula(driverItemFormulaItem))
                );

        //动因项 装配至 动因
        driverItems.stream()
                .collect(Collectors.groupingBy(DriverItem::getBelongDriverId))
                .forEach((key, value) ->
                        drivers.stream()
                                .filter(driver -> key.equals(driver.getId()))
                                .forEach(selectedDriver -> selectedDriver.setDriverItemList(value))
                );

        //动因  装配至  动因分组
        drivers.stream()
                .collect(Collectors.groupingBy(Driver::getBelongDriverGroupId))
                .forEach((key, value) ->
                        driverGroups.stream()
                                .filter(driverGroup -> key.equals(driverGroup.getKey()))
                                .forEach(selectedDriverGroup -> selectedDriverGroup.setDriverList(value))
                );
        //返回结果
        return driverGroups;
    }

    /**
     * 修改某一动因分组名称
     *
     * @param driverGroup 目标修改内容
     */
    @Transactional(rollbackFor = Exception.class)
    public void modifyDriverGroup(DriverGroup driverGroup) {
        abcDriverGroupDao.modifyDriverGroup(driverGroup);

        //更新abc模型的修改时间
        String modelId = driverGroup.getBelongModelId();
        abcBeanService.updateModifyTime(modelId);
    }


    /**
     * 动因分组 以 拖拽插入 方式 修改顺序
     * @param modelId 模型ID
     * @param dragIndex 拖拽动因分组索引
     * @param targetIndex 目标动因分组索引
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeDriverGroupOrder(String modelId,int dragIndex,int targetIndex) {
        List<DriverGroup> driverGroupList = getDriverGroupListByModelId(modelId);


        DriverGroup dragDriverGroup = driverGroupList.get(dragIndex);
        while (targetIndex != dragIndex){
            if (targetIndex < dragIndex) {
                DriverGroup  leftDriverGroup = driverGroupList.get(dragIndex - 1);
                driverGroupList.set(dragIndex, leftDriverGroup);

                dragIndex --;
            }else {
                DriverGroup   rightDriverGroup = driverGroupList.get(dragIndex + 1);
                driverGroupList.set(dragIndex, rightDriverGroup);

                dragIndex ++;
            }
        }
        driverGroupList.set(targetIndex, dragDriverGroup);

        abcDriverGroupDao.deleteDriverGroupsByModelId(modelId);
        abcDriverGroupDao.batchSaveDriverGroups(driverGroupList);
    }

    /**
     * 根据 动因分组ID 删除 一个动因分组
     *
     * @param driverGroupId 动因分组ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDriverGroup(String driverGroupId) {
        String modelId = getDriverGroupByDriverGroupId(driverGroupId).getBelongModelId();

        List<String> driverGroupIdList = new ArrayList<>();
        driverGroupIdList.add(driverGroupId);
        abcDriverService.batchDeleteDriversByDriverGroupIdList(driverGroupIdList);
        abcDriverGroupDao.deleteDriverGroupByDriverGroupId(driverGroupId);

        //更新abc模型的修改时间
        abcBeanService.updateModifyTime(modelId);
    }

    /**
     * 根据 模型id  删除 多个动因分组
     *
     * @param modelId 所属模型id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDriverGroupsByModelId(String modelId) {
        List<DriverGroup> driverGroupList = getDriverGroupListByModelId(modelId);
        List<String> driverGroupIdList = new ArrayList<>();
        for (DriverGroup driverGroup : driverGroupList) {
            driverGroupIdList.add(driverGroup.getKey());
        }
        abcDriverService.batchDeleteDriversByDriverGroupIdList(driverGroupIdList);
        abcDriverGroupDao.deleteDriverGroupsByModelId(modelId);

        //更新abc模型的修改时间
        abcBeanService.updateModifyTime(modelId);
    }
}
